
#include "encrypt/ed.h"
#define i2 (i*i)

JNIEXPORT jstring __raw_md5(JNIEnv *env,jobject jclazz, jstring str)
{
    char* szText = String2ByteArr(env,jclazz,str);

    MD5_CTX context = { 0 };
    MD5Init(&context);
    MD5Update(&context, szText, strlen(szText));
    unsigned char dest[16] = { 0 };
    MD5Final(dest, &context);
    (*env)->ReleaseStringUTFChars(env,str, szText);

    int i = 0;
    char szMd5[33] = { '\0' };
    for (i = 0; i < 16; i++)
    {
        sprintf(szMd5, "%s%02x", szMd5, dest[i]);
    }
    return (*env)->NewStringUTF(env,szMd5);
}

/*JNIEXPORT jstring raw_sha1(JNIEnv *env,jobject jclazz, jstring str)
{
    char* szText = String2ByteArr(env,jclazz,str);
    unsigned char result[21];
    char hexresult[41];
    size_t offset;
    SHA1_CTX ctx;
    SHA1Init(&ctx);
    SHA1Update( &ctx, (unsigned char const *)szText, strlen(szText));
    SHA1Final(result, &ctx);
    (*env)->ReleaseStringUTFChars(env,str, szText);

    for( offset = 0; offset < 20; offset++)
    {
        sprintf( ( hexresult + (2*offset)), "%02x", result[offset]&0xff);
    }
    return (*env)->NewStringUTF(env,hexresult);
}*/

JNIEXPORT jstring __get_app_sign(JNIEnv * env,jobject clazz, jobject ctx)
{
    return GSS(env, clazz, ctx);
}

/*JNIEXPORT jstring raw_aesEcbEncrypt(JNIEnv * env,jobject clazz,const uint8_t *pKeys, jstring str_)
{
    const char *in = (*env)->GetStringUTFChars(env, str_, JNI_FALSE);
    LOGE("%s", pKeys);
    char *baseResult = AES_PKCS5Padding_Encrypt(ECB, in, NULL, pKeys);
    (*env)->ReleaseStringUTFChars(env, str_, in);
//    return (*env)->NewStringUTF(env, baseResult);
    return charToString(env, baseResult);
}*/

/*JNIEXPORT jstring raw_aesEcbEncrypt2(JNIEnv * env,jobject clazz,jstring key, jstring str_)
{
//    const uint8_t *pKeys = (uint8_t *)(*env)->GetStringUTFChars(env, key, JNI_FALSE);
    const uint8_t *pKeys = getKey(env, key);
    return raw_aesEcbEncrypt(env, clazz, pKeys, str_);
}*/

/*JNIEXPORT jstring raw_aesCbcEncrypt(JNIEnv *env,jobject clazz,jstring iv, jstring key, jstring str_)
{
    const uint8_t *pKeys = getKey(env, key);
    const uint8_t *pIv = getKey(env, iv);
    const char *in = (*env)->GetStringUTFChars(env, str_, JNI_FALSE);
    char *baseResult = AES_PKCS5Padding_Encrypt(CBC, in, pIv, pKeys);
    (*env)->ReleaseStringUTFChars(env, str_, in);
    return charToString(env, baseResult);
}*/

/*JNIEXPORT jstring raw_aesCbcDecrypt(JNIEnv *env,jobject clazz,jstring iv, jstring key, jstring str_)
{
    const uint8_t *pKeys = getKey(env, key);
    const uint8_t *pIv = getKey(env, iv);
    const char *in = (*env)->GetStringUTFChars(env, str_, JNI_FALSE);
    char *baseResult = AES_PKCS5Padding_Decrypt(CBC, in, pIv, pKeys);
    (*env)->ReleaseStringUTFChars(env, str_, in);
    return charToString(env, baseResult);
}*/

/*JNIEXPORT jstring raw_aesEcbDecrypt(JNIEnv *env,jobject clazz, const uint8_t *pKey, jstring str_)
{
    const char *str = (*env)->GetStringUTFChars(env, str_, JNI_FALSE);
    char *desResult = AES_PKCS5Padding_Decrypt(ECB, str, NULL, pKey);
    (*env)->ReleaseStringUTFChars(env, str_, str);
//    return (*env)->NewStringUTF(env, desResult);
    return charToString(env, desResult);
}*/

/*JNIEXPORT jstring raw_aesEcbDecrypt2(JNIEnv *env,jobject clazz,jstring key, jstring str_)
{
//    const uint8_t *pKeys = (uint8_t *)(*env)->GetStringUTFChars(env, key, JNI_FALSE);
    const uint8_t *pKeys = getKey(env, key);
    return raw_aesEcbDecrypt(env, clazz, pKeys, str_);
}*/

/*unsigned char * getKey(JNIEnv *env, jstring key)
{
    const char *pKeys = (*env)->GetStringUTFChars(env, key, JNI_FALSE);
//    LOGE("%s", pKeys);
//    return b64_decode(pKeys, strlen(pKeys));
    return pKeys;
}*/


JNIEXPORT jint __write_str(JNIEnv *env, jobject jclazz, jstring path, jstring content)
{
    return StringAppendFile(env, jclazz, path, content);
}

JNIEXPORT jstring __read_str(JNIEnv *env, jobject clazz, jstring path)
{
    return ReadStringFile(env, clazz, path);
}

JNIEXPORT jint __delete_dir(JNIEnv *env, jobject jclazz, jstring path)
{
    return _delete_dir(env, jclazz, path);
}

JNIEXPORT jstring __get_pkg_name(JNIEnv *env, jobject thiz, jobject context)
{
    return GPN(env, thiz, context);
}

JNIEXPORT jstring __get_custom_sign(JNIEnv *env, jobject thiz, jobject context)
{
    jstring str = __get_app_sign(env, thiz, context);
    jstring name = __get_pkg_name(env, thiz, context);
    char *strText = String2ByteArr(env, thiz, str);
    char *strName = String2ByteArr(env, thiz, name);
    int strSize = strlen(strText);
    int nameSize = strlen(strName);
    char buf[strSize + nameSize + 1];
    strcpy(buf, strText);
    strcpy(buf, strName);
    buf[strSize + nameSize + 1] = '\0';
    jstring finalStr = (*env)->NewStringUTF(env, buf);
    //signature md5转换
    return __raw_md5(env, thiz, finalStr);
}

JNIEXPORT jstring __encode_base64(JNIEnv *env, jobject jclazz, jstring str)
{
    const char *strs = (*env)->GetStringUTFChars(env, str, JNI_FALSE);
    size_t t = strlen(strs);
    char *pResult = b64_encode(strs, t);
    return charToString(env, pResult);
}

JNIEXPORT jstring __decode_base64(JNIEnv *env, jobject jclazz, jstring str)
{
    const char *strs = (*env)->GetStringUTFChars(env, str, JNI_FALSE);
    size_t t = strlen(strs);
    unsigned char *pResult = b64_decode(strs, t);
    return charToString(env, pResult);
}

//
///**jvm虚拟机实例，用于开启子线程*/
//JavaVM *jvm;
//static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//static int flag = -1;
//static jobject jobj = NULL;
//static jmethodID mid = NULL;
//
////pthread中执行的函数
//void *nativeWork(void *args)
//{
//    JNIEnv *env = NULL;
//    //将本地线程连接到虚拟机上，这样本地线程才对虚拟机可见并且可以访问到虚拟机所在进程的资源
//    if (0 == (*jvm)->AttachCurrentThread(jvm, &env, NULL))
//    {
//        while (flag == 0)
//        {
//            if (jobj == NULL)
//            {
//                //进入等待
//                pthread_cond_wait(&cond, &mutex);
//            } else
//            {
//                //执行方法
//                (*env)->CallVoidMethod(env, jobj, mid);
//                (*env)->DeleteGlobalRef(env, jobj);
//                jobj = NULL;
//            }
//        }
//        (*jvm)->DetachCurrentThread(env);
//    }
//    return (void *) 1;
//}
//
//// Java和JNI函数的绑定表
//static JNINativeMethod method_table[] = {
//        { "md5", "(Ljava/lang/String;)Ljava/lang/String;", (void*)raw_md5 },
//        { "sha1", "(Ljava/lang/String;)Ljava/lang/String;", (void*)raw_sha1 },
//        { "getSign", "(Ljava/lang/Object;)Ljava/lang/String;", (void*)raw_getSign },
//        { "aesEncrypt", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void*)raw_aesEncrypt2 },
//        { "aesDecrypt", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void*)raw_aesDecrypt2 },
//        { "writeString", "(Ljava/lang/String;Ljava/lang/String;)I", (void*)WriteStringToFile} ,
//        { "readString", "(Ljava/lang/String;)Ljava/lang/String;", (void*)ReadStringFromFile }
//};
//
//// 注册native方法到java中
//static int registerNativeMethods(JNIEnv* env, const char* className,
//                                 JNINativeMethod* gMethods, int numMethods)
//{
//    jclass clazz;
//    clazz = (*env)->FindClass(env, className);
//    if (clazz == NULL) {
//        return JNI_FALSE;
//    }
//    if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
//        return JNI_FALSE;
//    }
//
//    return JNI_TRUE;
//}
//
//int register_ndk_load(JNIEnv *env)
//{
//    // 注册调用方法
//    return registerNativeMethods(env, JNIREG_CLASS, method_table, NELEM(method_table));
//}
//
//JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
//{
//    JNIEnv* env = NULL;
//    jint result = -1;
//
//    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
//        return result;
//    }
//
//    register_ndk_load(env);
//    //保存jvm句柄
//    jvm = vm;
//    // 返回jni的版本
//    return JNI_VERSION_1_4;
//}
//
//
////在卸载库时执行
//void JNI_OnUnLoad(JavaVM *vm, void *reserved)
//{
//    jvm = NULL;
//}